#include "code.h"
#ifdef LGVAG_COMPILER
#include "Globe.h"
#else
#include "RegDef.h"
#endif
#include <iostream>
using namespace std;
size_t jump_tag = 0;
cmd_val::cmd_val()
{
    this->op = NONE;
    this->regIdentity = 0;
    this->offset = 0;
}

cmd_val::cmd_val(cmd_val_type _op, unsigned reg, int offset)
{
    this->op = _op;
    this->regIdentity = reg;
    this->offset = offset;
}

cmd_code::cmd_code()
{
    this->op = HLT;
    this->type1 = cmd_val();
    this->type2 = cmd_val();
}

cmd_code::cmd_code(cctype _op, cmd_val t1, cmd_val t2)
{
    this->op = _op;
    this->type1 = t1;
    this->type2 = t2;
}

#ifdef _LGVAG_COMPILER

void print_register_name(unsigned reg)
{
    switch (reg)
    {
    case RAX:    cout << "%rax"; break;
    case EAX:    cout << "%eax"; break;
    case AX:    cout << "%ax"; break;
    case AH:    cout << "%ah"; break;
    case AL:    cout << "%al"; break;
    case RBX:    cout << "%rbx"; break;
    case EBX:    cout << "%ebx"; break;
    case BX:    cout << "%bx"; break;
    case BH:    cout << "%bh"; break;
    case BL:    cout << "%bl"; break;
    case RCX:    cout << "%rcx"; break;
    case ECX:    cout << "%ecx"; break;
    case CX:    cout << "%cx"; break;
    case CH:    cout << "%ch"; break;
    case CL:    cout << "%cl"; break;
    case RDX:    cout << "%rdx"; break;
    case EDX:    cout << "%edx"; break;
    case DX:    cout << "%dx"; break;
    case DH:    cout << "%dh"; break;
    case DL:    cout << "%dl"; break;
    case RSI:    cout << "%rsi"; break;
    case ESI:    cout << "%esi"; break;
    case SI:    cout << "%si"; break;
    case SIL:    cout << "%sil"; break;
    case RDI:    cout << "%rdi"; break;
    case EDI:    cout << "%edi"; break;
    case DI:    cout << "%di"; break;
    case DIL:    cout << "%dil"; break;
    case RBP:    cout << "%rbp"; break;
    case EBP:    cout << "%ebp"; break;
    case BP:    cout << "%bp"; break;
    case BPL:    cout << "%bpl"; break;
    case RSP:    cout << "%rsp"; break;
    case ESP:    cout << "%esp"; break;
    case SP:    cout << "%sp"; break;
    case SPL:    cout << "%spl"; break;
    case R8:    cout << "%r8"; break;
    case R8D:    cout << "%r8d"; break;
    case R8W:    cout << "%r8w"; break;
    case R8B:    cout << "%r8b"; break;
    case R9:    cout << "%r9"; break;
    case R9D:    cout << "%r9d"; break;
    case R9W:    cout << "%r9w"; break;
    case R9B:    cout << "%r9b"; break;
    case R10:    cout << "%r10"; break;
    case R10D:    cout << "%r10d"; break;
    case R10W:    cout << "%r10w"; break;
    case R10B:    cout << "%r10b"; break;
    case R11:    cout << "%r11"; break;
    case R11D:    cout << "%r11d"; break;
    case R11W:    cout << "%r11w"; break;
    case R11B:    cout << "%r11b"; break;
    case R12:    cout << "%r12"; break;
    case R12D:    cout << "%r12d"; break;
    case R12W:    cout << "%r12w"; break;
    case R12B:    cout << "%r12b"; break;
    case R13:    cout << "%r13"; break;
    case R13D:    cout << "%r13d"; break;
    case R13W:    cout << "%r13w"; break;
    case R13B:    cout << "%r13b"; break;
    case R14:    cout << "%r14"; break;
    case R14D:    cout << "%r14d"; break;
    case R14W:    cout << "%r14w"; break;
    case R14B:    cout << "%r14b"; break;
    case R15:    cout << "%r15"; break;
    case R15D:    cout << "%r15d"; break;
    case R15W:    cout << "%r15w"; break;
    case R15B:    cout << "%r15b"; break;
    case RIP:    cout << "%rip"; break;
    case EIP:    cout << "%eip"; break;
    case IP:    cout << "%ip"; break;
    case RFLAGS:  cout << "%rflags"; break;
    case EFLAGS:  cout << "%eflags"; break;
    case FLAGS:   cout << "%flags"; break;
    default:
        break;
    }
}
void cmd_code::Dump() const
{
    if (this->op == cmd_code::FLAG)
    {
        cout << ".L";
        cout << this->type1.offset;
        cout << ":";
        cout << endl;
        return;
    }
    switch (this->op)
    {
    case cmd_code::ADD:std::cout << "add"; break;
    case cmd_code::CMP:std::cout << "cmp"; break;
    case cmd_code::HLT:std::cout << "hlt"; break;
    case cmd_code::JE:
        cout << "je " << ".L" << this->type1.offset << endl;
        return; 
        break;
    case cmd_code::JNE: 
        cout << "je " << ".L" << this->type1.offset << endl;
        return; 
        break;
    case cmd_code::JMP: 
        cout << "je " << ".L" << this->type1.offset << endl;
        return; 
        break;
    case cmd_code::MOV:std::cout << "mov"; break;
    case cmd_code::POP:std::cout << "pop"; break;
    case cmd_code::PUSH:std::cout << "push"; break;
    case cmd_code::SUB:std::cout << "sub"; break;
    case cmd_code::SETE:std::cout << "sete"; break;
    case cmd_code::SETNE:std::cout << "setne"; break;
    case cmd_code::SETGE:std::cout << "setge"; break;
    case cmd_code::SETLE:std::cout << "setle"; break;
    case cmd_code::SETG:std::cout << "setg"; break;
    case cmd_code::SETL:std::cout << "setl"; break;
    case cmd_code::MOVZBL:std::cout << "movzbl"; break;
    case cmd_code::MUL:std::cout << "mul"; break;
    case cmd_code::IMUL:std::cout << "imul"; break;
    case cmd_code::DIV:std::cout << "div"; break;
    case cmd_code::NOT:std::cout << "not"; break;
    case cmd_code::IDIV:std::cout << "idiv"; break;
    case cmd_code::CLTD:std::cout << "cltd"; break;
    case cmd_code::SAL:std::cout << "sal"; break;
    case cmd_code::SAR:std::cout << "sar"; break;
    case cmd_code::AND:std::cout << "and"; break;
    case cmd_code::OR:std::cout << "or"; break;
    case cmd_code::XOR:std::cout << "xor"; break;
    default:std::cout << "NO!"; break;
    }
    if (this->type1.op == cmd_val::NONE)
    {
        std::cout << std::endl;
        return;
    }
    std::cout << " ";
    switch (this->type1.op)
    {
    case cmd_val::INTEGER:std::cout << "$" << this->type1.offset; break;
    case cmd_val::REGISTER:
        print_register_name(this->type1.regIdentity);
        break;
    case cmd_val::MEMORY:
        std::cout << this->type1.offset << "(";
        print_register_name(this->type1.regIdentity);
        std::cout << ")";
        break;
    }
    if (this->type2.op == cmd_val::NONE)
    {
        std::cout << std::endl;
        return;
    }
    std::cout << ",";
    switch (this->type2.op)
    {
    case cmd_val::INTEGER:std::cout << "$" << this->type2.offset; break;
    case cmd_val::REGISTER:
        print_register_name(this->type2.regIdentity);
        break;
    case cmd_val::MEMORY:
        std::cout << this->type2.offset << "(";
        print_register_name(this->type2.regIdentity);
        std::cout << ")";
        break;
    }
    std::cout << std::endl;
    return;
}

#endif